/* eslint-disable @typescript-eslint/no-unused-expressions */
import type { Handler } from 'mitt'
import type { RouteLocationNormalizedGeneric } from 'vue-router'
import mitt from 'mitt'

// 回调函数的类型
type Callback = (route: RouteLocationNormalizedGeneric) => void
const emitter = mitt()

const key = Symbol('ROUTE_CHANGE')

let latestRoute: RouteLocationNormalizedGeneric

// 设置最新的路由信息，触发路由变化事件
export function setRouteChange(to: RouteLocationNormalizedGeneric) {
  // 触发事件
  emitter.emit(key, to)
  // 缓存最新的路由信息
  latestRoute = to
}

// 订阅路由变化
// 单独用 watch 监听路由会浪费渲染性能,即watch(route)	每个组件独立监听，重复触发
// 而用发布订阅模式：单次事件触发，多组件共享，可自动卸载监听，避免内存泄漏
// 可优先选择使用该发布订阅模式去进行分发管理
export function useRouterListener() {
  // 回调函数集合
  const callbackList: Callback[] = []

  // 监听路由变化(可以选择立即执行)
  const listenerRouteChange = (callback: Callback, immediate = false) => {
    // 缓存回调函数
    callbackList.push(callback)
    // 监听事件
    emitter.on(key, callback as Handler)
    // 可以选择立即执行一次回调函数
    immediate && latestRoute && callback(latestRoute)
  }

  // 移除路由变化事件监听器
  const removeRouteListener = (callback: Callback) => {
    emitter.off(key, callback as Handler)
  }

  // 组件销毁前移除监听器
  onBeforeUnmount(() => {
    callbackList.forEach(removeRouteListener)
  })

  return { listenerRouteChange, removeRouteListener }
}
